/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * leafget
 * Copyright (C) xinliGG 2008 <xinliGG@gmail.com>
 * 
 * leafget is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * leafget is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <fcntl.h>
#include <netdb.h>
#include <memory.h>

#include "socket.h"

 Socket::Socket()
 {
	 sock = -1;
	 memset(&addr,0,sizeof(addr));
 }
 
 Socket::~Socket()
 {
	if( is_valid() )
	::close ( sock );
 }
 
 	/* intial functions */

const bool Socket::create ( void )
{
	sock = socket ( AF_INET, SOCK_STREAM, 0 );

	if( ! is_valid() )
		return false;

		/* TIME_WAIT - argh */
	int on = 1;
	if( setsockopt ( sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof( on ) ) == -1 )
		return false;

		/* secs timeout */
	struct timeval timeout;
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;

	if( setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof( timeout ) ) == -1)
		return false;

	return true;
}


const bool Socket::connect ( const std::string host, const int port )
{
	if( ! is_valid() )
		return false;

	addr.sin_family = AF_INET;
	addr.sin_port = htons (port);

	struct hostent *hostName = gethostbyname( host.c_str() );
	if( hostName == NULL )
		return false;

	addr.sin_addr.s_addr = *( ( unsigned long * ) hostName->h_addr );

	int status = ::connect ( sock, ( struct sockaddr * ) &addr, sizeof ( addr ) );
	if( status == 0 )
		return true;

	return false;
}

const bool Socket::close ( void )
{
	if( ! is_valid() )
		return false;

	::close ( sock );
	return true;
}


	/* data functions */

const bool Socket::send ( const std::string s ) const
{
	int status = ::send ( sock, s.c_str(), s.size(), MSG_NOSIGNAL );
	if( status == -1 )
		return false;
	else
		return true;
}

const int Socket::recv ( char *buf, const int bufSize ) const
{
	int recv_return = ::recv ( sock, buf, bufSize, 0 );
	
	return recv_return;
}

void Socket::set_non_blocking ( const bool b )
{
	int opts;

	opts = fcntl ( sock, F_GETFL );

	if ( opts < 0 )
		return;

	if ( b )
		opts = ( opts | O_NONBLOCK );
	else
		opts = ( opts & ~O_NONBLOCK );

	fcntl ( sock, F_SETFL,opts );

}


	/* get functions */
	
const int Socket::get_sock ( void ) const
{
	return sock;
}

	
	/* check functions */

const bool Socket::is_valid ( void ) const
{
	return sock != -1; 
}


/* EOF */

